package com.anlogic.sdk.bsp.ui;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

import com.anlogic.sdk.bsp.Constants;
import com.anlogic.sdk.bsp.model.PlatformModel;
import com.anlogic.sdk.tools.IBspTool;
import com.anlogic.sdk.tools.utils.ToolsUtils;
import com.anlogic.sdk.utils.EnvUtils;
import com.anlogic.sdk.utils.FileUtils;
import com.anlogic.sdk.utils.options.ChipType;
import com.anlogic.sdk.utils.options.OsType;

import org.eclipse.swt.widgets.FileDialog;

public class NewPlatformProjectWizardPage extends WizardPage {
	private Text projectNameText;
	private Button useDefaultLocButton;
	private Text locationText;
	private Button locationBrowse;
	private Combo hpfCombo;
	private Button hpfBrowse;
	private Combo osCombo;
	private Combo processorCombo;

	private PlatformModel model;

	private IBspTool bspTool;

	private String[] hpfList = Constants.DEMO_HPF_MAP.keySet().toArray(new String[0]);
	private String[] procList;
	private String[] hpfExtList = new String[] { ".hpf" };
	private String[] hpfFilterList = new String[] { "*.hpf" };
	
	public NewPlatformProjectWizardPage() {
		super("wizardPage");
		setTitle("New Platform Projet");
		setDescription("This wizard creates a new platform project from an hardware platform file.");
		this.model = new PlatformModel();
		this.bspTool = ToolsUtils.getBspTool();
		this.bspTool.setChip(ChipType.getDefault().getName());
	}

	@Override
	public void createControl(Composite parent) {
		Composite container = new Composite(parent, SWT.NULL);
		GridLayout layout = new GridLayout();
		container.setLayout(layout);
		layout.numColumns = 3;

		Label projectNameLabel = new Label(container, SWT.LEFT);
		projectNameLabel.setText("Project Name:");
		projectNameText = new Text(container, SWT.BORDER | SWT.SINGLE);
		projectNameText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1));

		useDefaultLocButton = new Button(container, SWT.CHECK);
		useDefaultLocButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false, 3, 1));
		useDefaultLocButton.setText("Use default Location");
		useDefaultLocButton.setSelection(true);

		Label projLocationLabel = new Label(container, SWT.LEFT);
		projLocationLabel.setText("Location:");
		locationText = new Text(container, SWT.BORDER | SWT.SINGLE);
		locationText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1));
		locationText.setText(EnvUtils.getWorkspacePath());
		locationText.setEnabled(false);
		locationBrowse = new Button(container, SWT.PUSH);
		locationBrowse.setText("Browse");
		locationBrowse.setEnabled(false);

		Label platformLabel = new Label(container, SWT.LEFT);
		platformLabel.setText("HPF File:");
		hpfCombo = new Combo(container, SWT.BORDER | SWT.DROP_DOWN);
		hpfCombo.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 1));
		String[] pltList = new String[hpfList.length + 1];
		pltList[0] = "None";
		for (int i = 1; i < pltList.length; i++) {
			pltList[i] = hpfList[i-1];
		}
		hpfCombo.setItems(pltList);
		hpfCombo.select(0);
		hpfBrowse = new Button(container, SWT.PUSH);
		hpfBrowse.setText("Browse");

		Label systemLabel = new Label(container, SWT.LEFT);
		systemLabel.setText("Operating system:");
		osCombo = new Combo(container, SWT.READ_ONLY);
		osCombo.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false, 2, 1));
		List<String> osList = new ArrayList<String>(this.bspTool.getOsNames());
		osList.remove(osList.indexOf(OsType.Linux.getName()));
		osCombo.setItems(osList.toArray(new String[0]));
		if (osList.contains("standalone")) {
			osCombo.setText("standalone");
		}
		this.model.setOs(osCombo.getText());
		
		procList = ChipType.getCpuNames(ChipType.getDefault().getName());
		Label processorLabel = new Label(container, SWT.LEFT);
		processorLabel.setText("Processor:");
		processorCombo = new Combo(container, SWT.READ_ONLY);
		processorCombo.setLayoutData(new GridData(SWT.BEGINNING, SWT.TOP, false, false, 2, 1));
		processorCombo.setItems(procList);
		processorCombo.select(0);
		this.model.setProc(processorCombo.getText());

		addListener();

		validatePage();

		setControl(container);
	}

	public void addListener() {
		projectNameText.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				validatePage();
			}
		});

		useDefaultLocButton.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				locationText.setEnabled(!useDefaultLocButton.getSelection());
				locationBrowse.setEnabled(!useDefaultLocButton.getSelection());
			}
		});

		locationText.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				validatePage();
			}
		});

		locationBrowse.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				DirectoryDialog dialog = new DirectoryDialog(getShell(), SWT.OPEN);
				String result = dialog.open();
				if (result != null && !result.isEmpty()) {
					locationText.setText(result);
				}
				validatePage();
			}
		});

		hpfCombo.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent e) {
				platformChanged();
				validatePage();
			}
		});

		hpfCombo.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				platformChanged();
				validatePage();
			}
		});

		hpfBrowse.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				FileDialog dialog = new FileDialog(getShell(), SWT.OPEN);
				dialog.setFilterExtensions(hpfFilterList);
				String result = dialog.open();
				if (result != null && !result.isEmpty()) {
					hpfCombo.setText(result);
					platformChanged();
				}
				validatePage();
			}
		});

		osCombo.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				model.setOs(osCombo.getText());
				validatePage();
			}
		});

		processorCombo.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent event) {
				model.setProc(processorCombo.getText());
				validatePage();
			}
		});
	}

	private boolean validatePage() {
		if (!validatePlatform()) {
			setPageComplete(false);
			return false;
		}
		
		if (!validateProject()) {
			setPageComplete(false);
			return false;
		}

		if (!validateLocation()) {
			setPageComplete(false);
			return false;
		}
		
		setMessage(null);
		setErrorMessage(null);

		setPageComplete(true);

		return true;
	}

	private boolean validateProject() {
		String projName = this.projectNameText.getText();
		if (projName == null || projName.length() == 0) {
			setErrorMessage("Project Name must be specified");
			return false;
		}
		if (!FileUtils.checkFileNameLegality(projName)) {
			setErrorMessage("Project name is illegal");
			return false;
		}
		IResource projectSource = ResourcesPlugin.getWorkspace().getRoot().findMember(new Path(projName));
		if (projectSource != null) {
			setErrorMessage("Project has already exist!");
			return false;
		}
		this.model.setProjName(projName);
		return true;
	}

	private boolean validateLocation() {
		String projLoc = locationText.getText();
		if (projLoc == null || projLoc.length() == 0) {
			setErrorMessage("Project location must be specified");
			return false;
		}
		if (!FileUtils.checkFilePathLegality(projLoc)) {
			setErrorMessage("Project location is illegal");
			return false;
		}
		projLoc = FileUtils.convertToLinuxPath(projLoc);
		IPath projLocPath = Path.fromPortableString(projLoc).append(this.projectNameText.getText());
		this.model.setProjLoc(projLocPath.toString());
		return true;
	}

	public boolean validatePlatform() {
		String hpfFile = hpfCombo.getText();
		if (hpfFile == null || hpfFile.length() == 0 || hpfFile.equals("None")) {
			setErrorMessage("Platform File must be specified");
			return false;
		}
		
		if (Constants.DEMO_HPF_MAP.containsKey(hpfFile)) {
			if (!validateHpf(Constants.DEMO_HPF_MAP.get(hpfFile))) {
				setErrorMessage("Please specify correct platform file");
				return false;
			}
			return true;
		}
			
		
		File plaform = new File(hpfFile);
		if (!plaform.exists()) {
			setErrorMessage("Platform file must be exist");
			return false;
		}

		boolean extensionMatched = false;
		for (String item : hpfExtList) {
			if (hpfFile.endsWith(item)) {
				extensionMatched = true;
				break;
			}
		}
		if (!extensionMatched) {
			setErrorMessage("Please specify correct platform file");
			return false;
		}

		if (!validateHpf(hpfFile)) {
			setErrorMessage("Please specify correct platform file");
			return false;
		}
		return true;
	}

	private boolean validateHpf(String hpfFile) {
		String chip = this.bspTool.getChipFromHpf(hpfFile);
		if (chip.equals("unknown")) {
			return false;
		}
		return true;
	}
	
	private void platformChanged() {
		String hpfFile = hpfCombo.getText();
		if (Constants.DEMO_HPF_MAP.containsKey(hpfFile)) {
			hpfFile = Constants.DEMO_HPF_MAP.get(hpfFile);
		}
		String chip = this.bspTool.getChipFromHpf(hpfFile);
		if (chip.equals("unknown")) {
			return;
		}
		this.model.setPlatformFile(hpfFile);
		processorCombo.setItems(ChipType.getCpuNames(chip));
		processorCombo.select(0);
		this.model.setChip(chip);
		this.model.setProc(this.processorCombo.getText());
		this.bspTool.setChip(chip);
		
		List<String> osList = new ArrayList<String>(this.bspTool.getOsNames());
		if (osList.contains(OsType.Linux.getName())) {
			osList.remove(osList.indexOf(OsType.Linux.getName()));
		}
		osCombo.setItems(osList.toArray(new String[0]));
		if (osList.contains("standalone")) {
			osCombo.setText("standalone");
		}
	}

	public PlatformModel getModel() {
		return this.model;
	}
}